using System;
using NHibernate.Dialect;
using NHibernate.SqlCommand;

namespace TelerikMvcGridCustomBindingHelper.NHibernate
{
    public class MsSql2008DialectBugFix : MsSql2008Dialect
    {
        public override SqlString GetLimitString(SqlString queryString, SqlString offset, SqlString limit)
        {
            var result = new SqlStringBuilder();

            if (offset == null)
            {
                // gets the right select insert point (after any query comments).
                var insertPoint = GetAfterSelectInsertPoint(queryString);

                result
                    .Add(queryString.Substring(0, insertPoint))
                    .Add(" TOP (")
                    .Add(limit)
                    .Add(") ")
                    .Add(queryString.Substring(insertPoint));

                return result.ToSqlString();
            }

            // remove potentially buggy query comments like: "/* criteria query */ "
            var comments = queryString.Substring(0, queryString.IndexOfCaseInsensitive("select"));
            var sqlString = queryString.Substring(comments.Length);

            sqlString = base.GetLimitString(sqlString, offset, limit);

            // add back the comments as they cannot offer more trouble.
            return sqlString.Insert(0, comments);
        }

        private static int GetAfterSelectInsertPoint(SqlString sql)
        {
            Int32 selectPosition;

            if ((selectPosition = sql.IndexOfCaseInsensitive("select distinct")) >= 0)
            {
                return selectPosition + 15; // "select distinct".Length;

            }
            if ((selectPosition = sql.IndexOfCaseInsensitive("select")) >= 0)
            {
                return selectPosition + 6; // "select".Length;
            }

            throw new NotSupportedException("The query should start with 'SELECT' or 'SELECT DISTINCT'");
        }
    }
}